import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { RoleEnum } from 'src/role/role.enum';
import { UserGuard } from 'src/role/role.guard';
import { ProjectService } from './project.service';
import { CurrentUser } from 'src/user/user.decorator';
import { UserSys } from 'src/user/userSys.entity';
import {
  Between,
  FindOptionsWhere,
  In,
  LessThan,
  Like,
  MoreThan,
  Not,
} from 'typeorm';
import { Project, ProjectStatus } from './project.entity';
import { UseLog } from 'src/log/useLog.decorator';
import { Forbidden, NotFound } from 'src/util/http';
import { WorkService } from 'src/work/work.service';
import { UserService } from 'src/user/user.service';
import { Work, WorkStatus } from 'src/work/work.entity';
import * as moment from 'moment';
import { DeductionService } from 'src/deduction/deduction.service';

@Controller('api/project')
@UseGuards(AuthGuard('jwt'))
@ApiTags('项目')
export class ProjectController {
  constructor(
    private readonly projectService: ProjectService,
    private readonly workService: WorkService,
    private readonly userService: UserService,
    private readonly deductionService: DeductionService,
  ) {}

  @Post('del')
  @UseLog('删除项目')
  @UseGuards(UserGuard([RoleEnum.director]))
  public async del(@Body() { ids }) {
    const entitys = await this.projectService.project.find({
      where: {
        id: In(ids),
      },
    });
    await this.deductionService.deduction.delete({
      project: {
        id: In(ids),
      },
    });
    await this.workService.work.delete({
      project: {
        id: In(ids),
      },
    });
    return await this.projectService.project.remove(entitys);
  }

  @Post('statistic')
  @ApiOperation({ summary: '工作量统计' })
  async postStatistic(
    @Body() { year, month, day, pid, userids },
    @CurrentUser() user: UserSys,
  ) {
    let date = year;
    const where: FindOptionsWhere<Work> = {};
    let time;
    if (!!year) {
      time = moment(year);
      where.createAt = Between(
        time.clone().startOf('year').toDate(),
        time.clone().endOf('year').toDate(),
      );
      if (!!month) {
        date += `-${month}`;
        time = moment(date);
        where.createAt = Between(
          time.clone().startOf('month').toDate(),
          time.clone().endOf('month').toDate(),
        );
        if (!!day) {
          date += `-${day}`;
          time = moment(date);
          where.createAt = Between(
            time.clone().startOf('days').toDate(),
            time.clone().endOf('days').toDate(),
          );
        }
      }
    }
    if (!!pid) {
      where.project = { id: pid };
    }
    if (user.role !== RoleEnum.boos) {
      where.system = { id: user.system.id };
    }
    const works = await this.workService.work.find({
      where,
      relations: ['project', 'user'],
    });
    return works;
  }

  @Get('statistic')
  @ApiOperation({ summary: '工作量统计' })
  async statistic(@CurrentUser() user: UserSys) {
    const where: FindOptionsWhere<Project> = {};
    if (user.role !== RoleEnum.boos) {
      where.system = { id: user.system.id };
    }
    const projects = await this.projectService.project.find({
      relations: ['works', 'works.user'],
      where,
    });
    return projects.map(({ id, name, works, score }) => ({
      name,
      works: works
        .filter((e) => {
          if (
            e.status === WorkStatus.applying ||
            e.status === WorkStatus.reject
          ) {
            return false;
          }
          if (user.role === RoleEnum.boos || user.role === RoleEnum.director)
            return true;
          return e.user.id === user.id;
        })
        .map(({ count, createAt }) => ({ count, createAt }))
        .reduce((data, item) => {
          const time = moment(item.createAt).format('YYYY-MM-DD');
          if (!data[time]) data[time] = 0;
          data[time] += item.count;
          return data;
        }, {}),
      score,
      id,
    }));
  }

  @Post('publishWork')
  @ApiOperation({ summary: '发布工作量' })
  async publishWork(@CurrentUser() user: UserSys, @Body() body) {
    return await this.projectService.createWork(
      body.count,
      body.comment,
      body.projectid,
      body.createAt,
      user,
    );
  }

  @Get('getmine/workdata/all')
  @ApiOperation({ summary: '获取所有我参与过的项目' })
  async getMineAllWorkData(@CurrentUser() user: UserSys) {
    const where: FindOptionsWhere<Work> = {
      user: {
        id: user.id,
      },
      status: WorkStatus.approved,
    };
    return this.workService.work.find({
      where,
      relations: ['project'],
      order: {
        id: 'desc',
      },
    });
  }

  @Get('getmine/workdata')
  @ApiOperation({ summary: '滚动获取所有我参与过的项目' })
  async getMineWorkData(@CurrentUser() user: UserSys, @Query('endid') endid) {
    const where: FindOptionsWhere<Work> = {
      user: {
        id: user.id,
      },
    };
    if (!!endid) {
      where.id = LessThan(endid);
    }
    return this.workService.work.find({
      where,
      relations: ['project'],
      order: {
        id: 'desc',
      },
      take: 10,
    });
  }

  @Get('getmine')
  @UseLog('获取我参与的项目')
  @UseGuards(UserGuard())
  public async getmine(@CurrentUser() user: UserSys) {
    const relations = ['system', 'works'];
    const where = this.projectService.getProjectWhere(user);
    if (!where) return [];
    where.status = ProjectStatus.running;
    return this.projectService.renderData(
      await this.projectService.project.find({
        where,
        relations,
        order: { id: 'desc' },
      }),
    );
  }

  @Get('getresponsibility')
  @ApiOperation({ summary: '获取管理的项目' })
  @UseGuards(UserGuard())
  public async getresponsibility(@CurrentUser() user: UserSys) {
    const where: FindOptionsWhere<Project> = {
      system: { id: user.system.id },
    };
    if (user.role !== RoleEnum.director && user.role !== RoleEnum.boos) {
      where.responsibility = { id: user.id };
    }
    return this.projectService.project.find({
      where,
      order: {
        id: 'desc',
      },
    });
  }

  @Get(':id/getmember')
  @ApiOperation({ summary: '获取项目员工' })
  @UseGuards(UserGuard())
  public async getmember(@Param('id') id: number) {
    return (
      await this.projectService.project.findOne({
        where: { id },
        relations: ['user'],
      })
    ).user;
  }

  @Get(':id/information')
  @UseLog('获取项目排行')
  @UseGuards(UserGuard())
  public async getInformation(
    @CurrentUser() user: UserSys,
    @Param('id') id: number,
  ) {
    const where = this.projectService.getProjectWhere(user);
    if (!where) throw Forbidden;
    where.status = ProjectStatus.running;
    where.id = id;
    const project = await this.projectService.project.findOne({
      where,
      relations: ['works', 'works.user'],
    });
    if (!project) throw NotFound;
    return this.projectService.get(project);
  }

  @Get(':id/works')
  @ApiOperation({ summary: '获取项目的工作量' })
  public async getWorks(@Param('id') id: number) {
    const project = await this.projectService.project.findOne({
      where: {
        id,
      },
      relations: ['works', 'works.user'],
    });
    if (!project) throw NotFound;
    return project.works;
  }

  @Post('publish')
  @UseLog({ summary: '发布项目' })
  @UseGuards(UserGuard([RoleEnum.director]))
  public async publish(@Body() body, @CurrentUser() user: UserSys) {
    return this.projectService.create(body, user.system);
  }

  @Post(':id/update')
  @UseLog('修改项目')
  public async update(@Body() body, @Param('id') id) {
    if (!(await this.projectService.project.exist({ where: { id } }))) {
      throw NotFound;
    }
    const entity = await this.projectService.project.findOne({
      where: {
        id,
      },
    });
    const responsibility = !!body.responsibility
      ? await this.userService.userSys.find({
          where: {
            id: In(body.responsibility.map((e) => e.id)),
          },
        })
      : [];
    const user = !!body.user
      ? await this.userService.userSys.find({
          where: {
            id: In(body.user.map((e) => e.id)),
          },
        })
      : [];
    await this.projectService.project.save({
      ...entity,
      ...body,
      responsibility,
      user,
    });
  }

  @Get('getProject')
  @UseLog({ summary: '获取项目列表' })
  @UseGuards(UserGuard([RoleEnum.director]))
  public async getProject(
    @CurrentUser() user: UserSys,
    @Query('name') name: string,
  ) {
    const where: FindOptionsWhere<Project> = {
      system: {
        id: user.system.id,
      },
      status: Not(ProjectStatus.done),
    };
    if (!!name) where.name = Like(`%${name}%`);
    return this.projectService.renderData(
      await this.projectService.project.find({
        where,
        relations: ['works', 'system', 'responsibility', 'user'],
        order: { id: 'DESC' },
      }),
    );
  }

  @Get('getDeptEmployeeScores')
  @ApiOperation({ summary: '获取部门员工得分统计' })
  @UseGuards(UserGuard())
  public async getDeptEmployeeScores(
    @CurrentUser() user: UserSys,
    @Query('deptId') deptId?: number,
    @Query('systemId') systemId?: number,
  ) {
    // 权限检查：项目经理只能查看本部门数据
    if (user.role === RoleEnum.manager && deptId && deptId !== user.dept.id) {
      throw Forbidden;
    }

    // 构建查询条件
    const whereConditions: FindOptionsWhere<Work> = {
      status: WorkStatus.approved, // 只统计已审核通过的工作量
    };

    // 根据用户权限设置查询范围
    if (user.role === RoleEnum.manager) {
      // 项目经理只能查看本部门
      whereConditions.dept = { id: user.dept.id };
      whereConditions.system = { id: user.system.id };
    } else if (user.role === RoleEnum.director || user.role === RoleEnum.boos) {
      // 总监和老板可以查看指定部门或职场
      if (deptId) {
        whereConditions.dept = { id: deptId };
      }
      if (systemId) {
        whereConditions.system = { id: systemId };
      } else if (!deptId) {
        // 如果没有指定部门，默认查看当前职场
        whereConditions.system = { id: user.system.id };
      }
    } else {
      // 其他角色无权限
      throw Forbidden;
    }

    // 查询工作量数据
    const works = await this.workService.work.find({
      where: whereConditions,
      relations: ['user', 'user.user', 'project', 'dept'],
    });

    // 按用户分组计算得分
    const userScores = new Map<number, {
      user: UserSys;
      totalScore: number;
      workCount: number;
      dept: string;
    }>();

    works.forEach(work => {
      const userId = work.user.id;
      const score = work.count * work.project.score;
      
      if (userScores.has(userId)) {
        const existing = userScores.get(userId);
        existing.totalScore += score;
        existing.workCount += work.count;
      } else {
        userScores.set(userId, {
          user: work.user,
          totalScore: score,
          workCount: work.count,
          dept: work.dept.name,
        });
      }
    });

    // 转换为数组并按得分排序（从高到低）
    const result = Array.from(userScores.values())
      .sort((a, b) => b.totalScore - a.totalScore)
      .map((item, index) => ({
        rank: index + 1,
        userId: item.user.id,
        userName: item.user.name,
        userAccount: item.user.account,
        deptName: item.dept,
        totalScore: Math.round(item.totalScore * 100) / 100, // 保留两位小数
        workCount: item.workCount,
      }));

    return result;
  }

  @Get(':id/:status/setStatus')
  @UseLog({ summary: '设置状态' })
  @UseGuards(UserGuard([RoleEnum.director]))
  public async setStatus(
    @Param('id') id: number,
    @Param('status') status: ProjectStatus,
  ) {
    const entity = await this.projectService.project.findOne({ where: { id } });
    entity.status = status;
    return await this.projectService.project.save(entity);
  }
}
